package org.wattdepot.cli.processor;

import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.wattdepot.cli.command.CarbonContentCommand;
import org.wattdepot.cli.command.CarbonStatsCommand;
import org.wattdepot.cli.command.ChartCommand;
import org.wattdepot.cli.command.EnergyStatsCommand;
import org.wattdepot.cli.command.FuelTypeCommand;
import org.wattdepot.cli.command.PowerStatsCommand;
import org.wattdepot.cli.command.PowerCommand;
import org.wattdepot.cli.command.DailySensorDataCommand;
import org.wattdepot.cli.command.SensorDataCommand;
import org.wattdepot.cli.command.SourcesCommand;
import org.wattdepot.cli.command.SummaryCommand;
import org.wattdepot.cli.command.TotalCommand;
import org.wattdepot.cli.command.TotalPowerCommand;
import org.wattdepot.cli.command.WattDepotCliCommand;
import org.wattdepot.client.WattDepotClient;

/**
 * Handles the commands from the command line interface.
 * 
 * @author George Lee, Yichi Xu
 *
 */
public class CommandProcessor {
  /** Contains instances of our classes.*/
  private Map<String, WattDepotCliCommand> commandTable;
  /** Contains the help string for all commands.*/
  private String helpMessage;
  /** The help message displayed to users. */
  private static final String HELP_QUIT_MESSAGE =
    "help\n" + "  This message\n" + "quit\n" + "  Exits the system\n";
  
  /**
   * Creates an instance of the CommandProcessor class.
   * 
   * @param client An instance of WattDepotClient which will be used by our commands.
   */
  public CommandProcessor(WattDepotClient client) {
    //Instantiate the commands.
    commandTable = new TreeMap<String, WattDepotCliCommand>();
    commandTable.put("chart", new ChartCommand(client));
    commandTable.put("powerstats", new PowerStatsCommand(client));
    commandTable.put("power", new PowerCommand(client));
    commandTable.put("dailysensordata", new DailySensorDataCommand(client));
    commandTable.put("sensordata", new SensorDataCommand(client));
    commandTable.put("sources", new SourcesCommand(client));
    commandTable.put("summary", new SummaryCommand(client));
    commandTable.put("total", new TotalCommand(client));
    commandTable.put("carboncontent", new CarbonContentCommand(client));
    commandTable.put("fueltypes", new FuelTypeCommand(client));
    commandTable.put("totalpower", new TotalPowerCommand(client));
    commandTable.put("energystats", new EnergyStatsCommand(client));
    commandTable.put("carbonstats", new CarbonStatsCommand(client));
  }
  
  /**
   * Processes the command received from the command loop.
   * 
   * @param command The command to be processed in the loop.
   * 
   * @return The results of the command.
   */
  public String processCommand(String command) {
    //Ignore empty commands.
    if (command.isEmpty()) {
      return "";
    }
    
    if ("help".equals(command)) {
      return this.getHelp();
    }
    if ("quit".equals(command) || "exit".equals(command)) {
      //Perhaps not the best way.
      throw new RuntimeException("Exiting CLI.");
    }

    StringTokenizer tokens = new StringTokenizer(command);
    String key = tokens.nextToken();
    if (commandTable.get(key) == null) {
      // Command couldn't be processed.
      return WattDepotCliCommand.reportUnknownCommand(command);
    }
    else {
      return commandTable.get(key).doCommand(command);
    }
  }
  

  /**
   * Generates helpful information. Commands are sorted alphabetically.
   * 
   * @return the help message.
   */
  private String getHelp() {
    if (this.helpMessage == null) {
      StringBuffer buffer = new StringBuffer(HELP_QUIT_MESSAGE);
      for (WattDepotCliCommand command : commandTable.values()) {
        buffer.append(command.getHelp());
      }
      
      this.helpMessage = buffer.toString();
    }
    
    return this.helpMessage;
  } 
}
